using LiteDB;
using PHMEE.VibrationDataGenerator.Data;
using Quartz;
using Quartz.Spi;

namespace PHMEE.VibrationDataGenerator.Services;

public class TaskManager
{
    private readonly TaskConfigRepository _taskConfigRepository;
    private readonly VibDataCacheService _vibDataCacheService;
    private readonly WeiLiVibDataFilesService _weiLiVibDataFilesService;
    private readonly ChannelConfigRepository _channelConfigRepository;
    private readonly IScheduler _scheduler;

    public TaskManager(ISchedulerFactory schedulerFactory,
        IJobFactory jobFactory,
        TaskConfigRepository taskConfigRepository,
        VibDataCacheService vibDataCacheService,
        WeiLiVibDataFilesService weiLiVibDataFilesService,
        ChannelConfigRepository channelConfigRepository)
    {
        _taskConfigRepository = taskConfigRepository;
        _vibDataCacheService = vibDataCacheService;
        _weiLiVibDataFilesService = weiLiVibDataFilesService;
        _channelConfigRepository = channelConfigRepository;
        _scheduler = schedulerFactory.GetScheduler().GetAwaiter().GetResult();

        // 使用自定义的 JobFactory
        _scheduler.JobFactory = jobFactory;
    }

    /// <summary>
    /// 启动任务调度器
    /// </summary>
    public async Task StartAsync()
    {
        await _scheduler.Start();

        // 从 LiteDB 加载任务并调度
        var tasks = LoadRunningTasksFromDatabase();
        foreach (var taskConfig in tasks)
        {
            await ScheduleJob(taskConfig);
        }
    }

    private async Task ScheduleJob(TaskConfig taskConfig)
    {
        var job = JobBuilder.Create<VibDataGenerateDynamicTaskJob>()
            .WithIdentity(taskConfig.Id.ToString())
            .UsingJobData(CreateJobDataMap(taskConfig)) // 将任务配置传递给 Job
            .Build();

        var trigger = TriggerBuilder.Create()
            .WithIdentity($"{taskConfig.Id}_Trigger")
            .WithCronSchedule(taskConfig.CronExpression)
            .Build();

        await _scheduler.ScheduleJob(job, trigger);
    }

    private JobDataMap CreateJobDataMap(TaskConfig taskConfig)
    {
        var channelConfig = _channelConfigRepository.GetConfigById(taskConfig.ChannelConfigId);

        JobDataMap? jobDataMap;

        // Channel 数据源类型为 JianLong 时
        if (channelConfig.DataSrcType == DataSrcType.JianLong)
        {
            var vibDataEnumerator = _vibDataCacheService.CreateDataEnumerator();

            jobDataMap = new JobDataMap
            {
                { "TaskConfig", taskConfig },
                { "ChannelConfig", channelConfig },
                { "VibDataEnumerator", vibDataEnumerator }
            };
        }
        // Channel 数据源类型为 WeiLi 时
        else if (channelConfig.DataSrcType == DataSrcType.WeiLi)
        {
            var weiLiVibDataEnumerator = _weiLiVibDataFilesService.CreateWeiLiVibDataEnumerator(channelConfig.DaqId, channelConfig.DaqChNumber);
            jobDataMap = new JobDataMap
            {
                { "TaskConfig", taskConfig },
                { "ChannelConfig", channelConfig },
                { "WeiLiVibDataEnumerator", weiLiVibDataEnumerator }
            };
        }
        else
        {
            throw new Exception("Unsupported DataSrcType");
        }

        return jobDataMap;
    }

    /// <summary>
    /// 添加任务
    /// </summary>
    /// <param name="taskConfig"></param>
    public async Task AddTask(TaskConfig taskConfig)
    {
        // 如果任务状态为 Running，则调度新任务
        if (taskConfig.Status == VibDataGenerateTaskStatus.Running)
        {
            // 调度新任务
            await ScheduleJob(taskConfig);
        }
    }

    /// <summary>
    /// 更新任务
    /// </summary>
    /// <param name="taskConfig"></param>
    /// <param name="oldTaskConfig"></param>
    public async Task UpdateTask(TaskConfig taskConfig, TaskConfig oldTaskConfig)
    {
        // 只要任务有更新，就重新调度任务

        // 如果旧任务正在运行，则删除旧任务触发器
        if (oldTaskConfig.Status == VibDataGenerateTaskStatus.Running)
        {
            // 删除旧任务触发器
            await _scheduler.DeleteJob(new JobKey(taskConfig.Id.ToString()));
        }

        // 如果更新后的任务状态为 Running，则调度新任务
        if (taskConfig.Status == VibDataGenerateTaskStatus.Running)
        {
            // 调度新任务
            await ScheduleJob(taskConfig);
        }
    }

    /// <summary>
    /// 删除任务
    /// </summary>
    /// <param name="taskId"></param>
    public async Task DeleteTask(ObjectId taskId)
    {
        // 删除任务触发器
        await _scheduler.DeleteJob(new JobKey(taskId.ToString()));
    }

    /// <summary>
    /// 停止任务调度器
    /// </summary>
    public async Task StopAsync()
    {
        await _scheduler.Shutdown();
    }

    /// <summary>
    /// 读取所有正在运行的任务配置
    /// </summary>
    /// <returns></returns>
    private List<TaskConfig> LoadRunningTasksFromDatabase()
    {
        return _taskConfigRepository.GetAllTasks().Where(t => t.Status == VibDataGenerateTaskStatus.Running).ToList();
    }
}